package com.autumn.platform.web.exceptionresolver;

import java.util.Properties;
import java.util.Set;

import javax.validation.ValidationException;

import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.NoHandlerFoundException;

import com.autumn.platform.core.Utils;
import com.autumn.platform.core.context.response.IResponse;
import com.autumn.platform.core.context.response.impl.Response;
import com.autumn.platform.core.exception.CodableException;
import com.autumn.platform.core.spring.SpringHolder;
import com.autumn.platform.web.HttpStatus;

public class ExceptionStatusResolver {

    private static final Properties httpCodes = new Properties();

    static {
        try {
            Set<Resource> resources = SpringHolder.getResources("classpath*:config/**/exception-http-code-mapping.properties");
            if (null != resources) {
                for (Resource resource : resources) {
                    PropertiesLoaderUtils.fillProperties(httpCodes, resource);
                }
            }
        } catch (Exception e) {
        }
    }

    public static IResponse resolveStatus(Throwable t) {
        if (t instanceof HttpRequestMethodNotSupportedException) {
            return HttpStatus._405;
        } else if (t instanceof HttpMediaTypeNotSupportedException) {
            return HttpStatus._415;
        } else if (t instanceof HttpMediaTypeNotAcceptableException) {
            return HttpStatus._406;
        } else if (t instanceof MissingPathVariableException) {
            return HttpStatus._500;
        } else if (t instanceof MissingServletRequestParameterException) {
            return HttpStatus._400;
        } else if (t instanceof ServletRequestBindingException) {
            return HttpStatus._400;
        } else if (t instanceof ConversionNotSupportedException) {
            return HttpStatus._500;
        } else if (t instanceof TypeMismatchException) {
            return HttpStatus._400;
        } else if (t instanceof HttpMessageNotReadableException) {
            return HttpStatus._400;
        } else if (t instanceof HttpMessageNotWritableException) {
            return HttpStatus._500;
        } else if (t instanceof MethodArgumentNotValidException) {
            return HttpStatus._400;
        } else if (t instanceof MissingServletRequestPartException) {
            return HttpStatus._400;
        } else if (t instanceof BindException) {
            return HttpStatus._400;
        } else if (t instanceof NoHandlerFoundException) {
            return HttpStatus._404;
        } else if (t instanceof AsyncRequestTimeoutException) {
            return HttpStatus._503;
        } else if (t instanceof ValidationException) {
            return HttpStatus._400;
        } else if (t instanceof CodableException) {
            CodableException ce = (CodableException) t;
            String code = ce.getCode();
            String httpCode = httpCodes.getProperty(code);
            if (Utils.isBlank(httpCode)) {
                return new Response(code, t.getLocalizedMessage());
            } else {
                return new Response(httpCode, t.getLocalizedMessage());
            }
        } else {
            return HttpStatus._500;
        }
    }
}
